/* 
 * File:   BlockLinkedList.h
 * Author: unshaikh
 *
 * Created on February 4, 2011, 10:17 AM
 */

#ifndef BLOCKLINKEDLIST_H
#define	BLOCKLINKEDLIST_H


#include "Block.h"
#include "Disk.h"
#include <iostream>
#include <unistd.h>
#include <stdio.h>

class BlockLinkedList {
public:
    /**
     * Default constructor for BlockedLinkedList
     */
    BlockLinkedList();
    
    /**
     * Uses the disk and block size given to initialize those data members of 
     * the object. Other data members get default initialization. Does not 
     * modify the Disk.
     * @param disk to use in operations on the BlockLinkedList thus constructed.
     * @param blockSize size of the blocks in this BlockLinkedList. 
     */
    BlockLinkedList(Disk* disk, int blockSize);

    /**
     * Create a new BlockLinkedList using the disk, and block size of another
     * BlockLinkedList. Does not modify the Disk.
     * @param b Data member values are copied over from this other
     * BlockLinkedList.
     */
    BlockLinkedList(BlockLinkedList* b);

    /**
     * Generates a one block BlockLinkedList. Modifies the disk. Assumes the
     * disk andd block size data members of this BlockLinkedList have been
     * properly initialized.
     * @param blockNumber is the block number on disk of the first (and only)
     * block of this BlockLinkedList. Resets the data in the m_buffer of this
     * block before writing to disk.
     * @return
     */
    bool Initialize(int blockNumber);

    /**
     * Returns the amount of "usable" data within each block on disk.
     * @return Returns the block size in bytes of the blocks associated with
     * the BlockLinkedList. The returned value will be 4 bytes less than the
     * block size of the Disk associated with this BlockLinkedList because the
     * first four bytes of each block's m_buffer are reserved for the
     * "next pointer".
     */
    int GetBlockSize();

    /**
     * Return the number of blocks currently in this BlockLinkedList.
     * @return the number of blocks currently in this BlockLinkedList.
     */
    int GetNumberOfBlocks();

    /**
     * Unlinks the block that is the starting block of this BlockLinkedList.
     * Makes changes on disk.
     * @return the Block representing the unlinked block. This Block isn't
     * linked into any BlockLinkedList. The next pointer of the Block points to 
     * -1. It is the responsibility of the caller to deallocate the returned
     * Block.
     */
    Block* UnlinkBlock();

    /**
     * Add another block to the end of this BlockLinkedList. Makes changes on
     * disk. Assumes that the ending block number for this BlockLinkedList is
     * valid.
     * @param newBlock newBlock is the new Block. This block should have
     * already been removed from the BlockLinkedList upon which it was
     * previously. Resets the data in the m_buffer of this block before
     * writing to disk.
     * @return
     */
    bool AddBlock(Block* newBlock);
    int GetStartBlockNumber();
    int GetEndBlockNumber();
    Disk* GetDisk();

    /**
     * After this call, GetCurrentBlock will return the first block in the
     * BlockLinkedList. After this call, a call to GetNextBlock will seek to
     * the second Block (if any) in the BlockLinkedList. No changes are made
     * to disk.
     */
    void Rewind();

    Block* GetCurrentBlock();

    /**
     * Seeks the BlockLinkedList to the next block, unless GetCurrentBlock()
     * returns null. Changes the value returned by GetCurrentBlock() to the
     * next Block in the file, unless no more Blocks exist. In this case,
     * GetCurrentBlock() will now return null. No changes are made to disk.
     */
    void GetNextBlock();///Look into return

    /**
     * Outputs to the console the sequence of block numbers comprising this
     * BlockLinkedList. Rewind state is changed by this call.
     */
    void Output();

    /**
     * Replaces the m_buffer of the GetCurrentBlock() Block on Disk of this
     * BlockLinkedList with the m_buffer of the block given as a parameter.
     * The first four bytes of the m_buffer of the blk parameter are modified--
     * and replaced with the Disk block's next pointer. The block number of the
     * blk parameter is also modified.
     * @param blk blk to replace the GetCurrentBlock() Block. But its next
     * pointer should also be modified.
     * @return
     */
    bool Replace(Block *blk);

    /**
     * Count the number of blocks in a BlockLinkedList by traversing the Blocks
     * from the start Block to the end Block. This may be useful for debugging.
     * Changes the Rewind state of the BlockLinkedList.

     * @return number of blocks in BlockLinkedList
     */
    int CountBlocks();

    static void Test();
    /**
     * Default destructor
     */
    ~BlockLinkedList();
protected:
    Disk* m_disk;
    int m_blockSize;
    int m_numberOfBlocks;
    int m_startBlockNumber;
    int m_endBlockNumber;
    Block* m_seek;
private:

};

#endif	/* BLOCKLINKEDLIST_H */

